package cn.thr.pethome.logininfo.service.impl;

import cn.thr.pethome.jwt.PayloadData;
import cn.thr.pethome.logininfo.domain.LoginRO;
import cn.thr.pethome.logininfo.domain.LoginVO;
import cn.thr.pethome.logininfo.domain.Logininfo;
import cn.thr.pethome.logininfo.mapper.LogininfoMapper;
import cn.thr.pethome.logininfo.service.ILogininfoService;
import cn.thr.pethome.base.service.Impl.BaseServiceImpl;
import cn.thr.pethome.menu.domain.Menu;
import cn.thr.pethome.menu.service.IMenuService;
import cn.thr.pethome.menu.service.impl.MenuServiceImpl;
import cn.thr.pethome.role.mapper.RoleMapper;
import cn.thr.pethome.user.domain.Employee;
import cn.thr.pethome.user.domain.User;
import cn.thr.pethome.user.mapper.UserMapper;
import cn.thr.pethome.user.service.IEmployeeService;
import cn.thr.pethome.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static cn.thr.pethome.menu.service.impl.MenuServiceImpl.MENU_LIST;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author thr
 * @since 2023-01-31
 */
@Service
public class LogininfoServiceImpl extends BaseServiceImpl<Logininfo> implements ILogininfoService {
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private IEmployeeService employeeService;

    @Autowired
    private RoleMapper roleMapper;

    @Value("${jwt.rsa.pri}")
    private String pri;

    @Autowired
    private IMenuService menuService;

    @Autowired
    private UserMapper userMapper;


    @Override
    public AjaxResult account(LoginRO login) {
        if(login.getType() == null){
            throw new BusinessException("非法访问");
        }
        if(login.getPassword() == null || "".equals(login.getPassword().trim())){
            throw new BusinessException("密码不能为空");
        }
        if(login.getUsername() == null || "".equals(login.getUsername().trim())){
            throw new BusinessException("密码不能为空");
        }
        Logininfo account = logininfoMapper.account(login);
        if(account==null){
            throw new BusinessException("用户名或者密码错误");
        }
        if(login.getAutoLogin()){
            String password = login.getPassword();
            String salt = account.getSalt();//加密盐值
            String s = MD5Utils.encrypByMd5(password + salt);
            if(!account.getPassword().equals(s)){
                throw new BusinessException("用户名或者密码错误");
            }
        }
        return getJwtToken(account);
    }

    private AjaxResult getRedisToken(Logininfo account) {
        // 128位的随机数
        String token = StrUtils.getComplexRandomString(128);
        redisTemplate.opsForValue().set(token, account,30, TimeUnit.MINUTES);
        Long id = account.getId();  //Logininfo 这张表的id
        Employee byLogininfoId = employeeService.findByLogininfoId(id);//根据employee 里的LogininfoId 查询Logininfo这个表
        Long empId = byLogininfoId.getId();  //这是employee 的 id
        List<Long> roles = employeeService.findRoleByEmpId(empId);  //employee 的 id 来查询  employee——role 角色这张表  获取角色
        //通过t_role_permission   role_id 去查询 t_permission中间表的id  只需要中间表的sn
        List<String> permissionsByRoleIds = roleMapper.getPermissionsByRoleIds(roles); //获取到自己角色的权限 取到sn
        redisTemplate.opsForValue().set(token+"permission",permissionsByRoleIds,30, TimeUnit.MINUTES);

        LoginVO loginVO = new LoginVO();
        loginVO.setToken(token);
        loginVO.setLogininfo(account);
        return AjaxResult.success().setData(loginVO).setMsg("managerLogin");
    }

    private AjaxResult getJwtToken(Logininfo account){
        LoginVO loginVO = new LoginVO();
        Long id1 = account.getId();
        try {
            //放入载荷的东西
            PayloadData payloadData = new PayloadData();
            //判断是不是管理员
            if(account.getType() == 0){
                Employee employee = employeeService.findByLogininfoId(id1); // 查询管理员的id
                //Employee employee = new Employee();
                //BeanUtils.copyProperties(account,employee);
                payloadData.setAdmin(employee); //如果是管理员就吧管理员的信息设置进去

                Long id = account.getId();  //Logininfo 这张表的id
                Employee byLogininfoId = employeeService.findByLogininfoId(id);//根据employee 里的LogininfoId 查询Logininfo这个表
                Long empId = byLogininfoId.getId();  //这是employee 的 id
                List<Long> roles = employeeService.findRoleByEmpId(empId);  //employee 的 id 来查询  employee——role 角色这张表  获取角色
                //通过t_role_permission   role_id 去查询 t_permission中间表的id  只需要中间表的sn
                List<String> permissionsByRoleIds = roleMapper.getPermissionsByRoleIds(roles); //获取到自己角色的权限 取到sn
                //把权限加入进去
                payloadData.setPermissions(new HashSet<>(permissionsByRoleIds));

                //菜单很特殊
                List<Menu> all = menuService.findAll();
                //构建自己的菜单树
                List<Long> menuByRole = menuService.findMenuByRole(roles);
                //自己的id
                List<Menu> c = new ArrayList<>();
                for (Menu menu : all) {
                    for (Long aLong : menuByRole) {
                        if(menu.getId().equals(aLong)){
                            c.add(menu);
                        }
                    }
                }
                //这是父亲的id
                List<Long> parent = c.stream()
                        .map(Menu::getParentId) //只要ParentId
                        .distinct() //去除重复值
                        .collect(Collectors.toList());

                List<Menu> p = new ArrayList<>();
                for (Menu menu : all) {
                    for (Long aLong : parent) {
                        if(menu.getId().equals(aLong)){
                            p.add(menu);
                        }
                    }
                }

                p.forEach(menu -> {
                    c.forEach(menu1 -> {
                        if(menu1.getParentId() .equals(menu.getId())){
                            menu.getChildren().add(menu1);
                        }
                    });
                });

                payloadData.setMenus(p);

            }else { //如果是用户就把用户的信息放入进去
                User user = userMapper.findByLogininfoId(account.getId());
                BeanUtils.copyProperties(account,user);
                payloadData.setUser(user);
            }


            // 1 生成token
            PrivateKey privateKey = RsaUtils.getPrivateKey(JwtUtils.class.getClassLoader().getResource(pri).getFile());
            String token = JwtUtils.generateTokenExpireInMinutes(payloadData, privateKey, 30);
            System.out.println(token);

            //返回回去
            loginVO.setToken(token);
            loginVO.setLogininfo(account);
            loginVO.setEmployee(payloadData.getAdmin());
            loginVO.setUser(payloadData.getUser());
            loginVO.setMenus(payloadData.getMenus());
            loginVO.setPermissions(payloadData.getPermissions());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return AjaxResult.success().setData(loginVO).setMsg("managerLogin");
    }
}
